# Module to render openoffice files using Django.

from django.http import HttpResponse, HttpResponseRedirect
from django.template import Context, Template
from StringIO import StringIO
import os, zipfile
from django.conf import settings

class ood:
    """ A class representing an openoffice document """
    
    # The directory, inside the template path where the original file is
    # decompressed
    template_dir=""
    # A file objetc where we store the generated file
    file=None
    # The kind of open document file that we are, both an extension name and a
    # a mime_type
    extension_type=""
    mime_type=""
    
    def __init__(self,temp_dir,type):
        self.template_dir=temp_dir
        if type=="odt" or type=="text" :
            self.extension_type="odt"
            self.mime_type="'application/vnd.oasis.opendocument.text'"
        elif type=="ods" or type=="spreadsheet" or type=="calc" :
            self.extension_type="ods"
            self.mime_type="'application/vnd.oasis.opendocument.spreadsheet'"
        else :
            raise TypeError
                
    def render_main(self,context):
        """ Renders the main file 
        Expects a context dictionary, similar to other django context"""
        
        # Prepare the file 
        datos = StringIO()
        list=zipfile.ZipFile(datos,mode="w",compression=zipfile.ZIP_DEFLATED)
        current_dir=".error."
        for temp_dir in settings.TEMPLATE_DIRS:
            if os.path.isdir(temp_dir + "/" + self.template_dir):
                current_dir = temp_dir + "/" + self.template_dir
                for archivo in os.listdir(current_dir):
                    if os.path.isfile(current_dir + '/' + archivo):
                        if archivo[-3:]=="xml":
                            #  This file should be templated
                            temp=Template(file(current_dir + '/' + archivo,'r').read())
                            cont=Context(context)
#                            proba=temp.render(cont)
#                            raise pepe
                            list.writestr(archivo,temp.render(cont).encode('ascii','xmlcharrefreplace'))
                        else :
                            # For now, we only render xml files
                            list.write(current_dir + '/' + archivo,archivo,zipfile.ZIP_DEFLATED)
                    elif os.path.isdir(current_dir + '/' + archivo) :
                        # If the file is a dir, we scan it
                        # We are not expecting subdirs in an odt file, so we don't check for them.
                        for archivo2 in os.listdir(current_dir +'/' + archivo):
                            if os.path.isfile(current_dir + '/' + archivo + '/' + archivo2) :
                                list.write(current_dir + '/' + archivo + '/' + archivo2,archivo + '/' + archivo2,zipfile.ZIP_DEFLATED)
    
        list.close()
        self.file=datos
    
        # Test if the dir was found
        if current_dir==".error." :
            raise Templatenotfound

    def get_response(self,filename):
        """ Returns a HttpResponse with the document, named filename"""
        if self.file==None :
            raise NameError
        else:
            response = HttpResponse(mimetype=self.mime_type)
            response['Content-Disposition'] = 'attachment; filename=' + filename
            response.write(self.file.getvalue())
            
            return response

    def copy_object(self,origin,dest,document_type,context):
        """ Copy and render an ooo integrated object (an object defined by an
        open document xml file).
        An object is a subdir of the file object, a new subdir will be created
        name dest, and all the files inside origin that have a .xml extension
        will be rendered as django templates """
        
        # We open the zip file to append the new dirs
        list=zipfile.ZipFile(self.file,"a",zipfile.ZIP_DEFLATED)
        # We need to alter the manifest file, we load it from the file
        manifest_org=list.read('META-INF/manifest.xml')
        # We deletele the closing tags
        manifest=manifest_org.replace("</manifest:manifest>","")

        # We search for the ooo dir
        for temp_dir in settings.TEMPLATE_DIRS:
            if os.path.isdir(temp_dir + "/" + self.template_dir):
                current_dir = temp_dir + "/" + self.template_dir
                # Current_dir is the ooo base dir
                # We check if the object is there and it is a dir
                if os.path.isdir(current_dir + '/' + origin) :
                    # We process the files of the object
                    for cur_file in os.listdir(current_dir + '/' + origin):
                        if cur_file[-3:]=="xml" :
                            # If the file name ends in xml  we render it
                            temp=Template(file(current_dir + '/' + origin + '/' + cur_file,'r').read())
                            cont=Context(context)
                            list.writestr(dest + '/' + cur_file,temp.render(cont))
                            # We add it to the manifest file
                            manifest = manifest + '<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="' + dest + "/" + cur_file +'"/>\n'
                        else :
                            # Just add the file as it is
                            list.write(current_dir + '/' + origin+ '/' + cur_file,dest + '/' + file,zipfile.ZIP_DEFLATED)
                            
        # We need to add the new object as a whole to the manifest file
        manifest=manifest + '<manifest:file-entry manifest:media-type="' + document_type + '" manifest:full-path="' +dest +'/"/>\n'
        manifest = manifest + "</manifest:manifest>"

        # Create a new zip file with the new manifest
        new_data=StringIO()
        new_list=zipfile.ZipFile(new_data,mode="w")
        for archivo in list.namelist() :
            if archivo=="META-INF/manifest.xml" :
                new_list.writestr('META-INF/manifest.xml',manifest)
            else :
                new_list.writestr(archivo,list.read(archivo))
        
        list.close()
        new_list.close()
        self.file=new_data
